#include "apue.h"

#include <errno.h>
#include <fcntl.h>
#include <semaphore.h>
#include <sys/wait.h>
#include <time.h>

const char *name = "/sem";

int main()
{
  pid_t pid;
  sem_t *sem;

  pid = fork();
  if (pid < 0) {
    printf("fork failed.\n");
  } else if (pid > 0) {
    // parent
    // 创建信号量，初始值为0
    sem = sem_open(name, O_CREAT, FILE_MODE, 0);

    // 非阻塞获取信号量
    if (sem_trywait(sem) == -1) {
      if (errno == EAGAIN) {
        printf("sem_trywait can't get semaphore.\n");
      }
    } else {
      printf("parent: get semaphore.\n");
    }

    // 阻塞方式获取信号量
    if (sem_wait(sem) == -1) {
      printf("sem_wait failed.\n");
    } else {
      printf("parent: get semaphore.\n");
    }

    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    ts.tv_sec += 3; /* 超时3秒 */
    // 阻塞一段时间
    printf("parent: get semaphore with timeout.\n");
    if (sem_timedwait(sem, &ts) == -1) {
      if (errno == ETIMEDOUT) {
        printf("sem_timedwait timeout.\n");
      }
    } else {
      printf("parent: get semaphore.\n");
    }

    wait(NULL);
    return 0;
  } else {
    // child
    sleep(1);
    // 打开现有的信号量
    sem = sem_open(name, 0);
    // 释放信号量
    if (sem_post(sem) == -1) {
      printf("sem_post failed.\n");
    } else {
      printf("child : post semaphore\n");
    }
    return 0;
  }
  return 0;
}